package com.ndp.fb.rdb.db.impl.mapper;

import com.ndp.fb.exception.UnCheckedException;
import com.ndp.fb.rdb.annotation.Column;
import com.ndp.fb.rdb.annotation.ColumnType;
import com.ndp.fb.util.ReflectUtil;
import org.springframework.jdbc.core.RowMapper;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;

/**
 * Created by infi.he on 2016/2/1.
 */
public class AutoRowMapper<T> implements RowMapper {

    private Class<T> clazz;

    public AutoRowMapper(Class<T> clazz) {
        this.clazz = clazz;
    }

    public Class<T> getClazz() {
        return clazz;
    }

    @SuppressWarnings("unchecked")
    @Override
    public T mapRow(ResultSet rs, int k) throws SQLException {
        T t = null;
        try {
            //获取有注解Column 的字段。
//            List<Field> list = ReflectUtil.getAnnoFieldList(clazz, Column.class);
            List<Field> list = ReflectUtil.getFieldsRecurse(clazz);
            t = clazz.newInstance();
            ResultSetMetaData metaData = rs.getMetaData();
            int count = metaData.getColumnCount();
            for (int i = 1; i <= count; i++) {
                String columnName = metaData.getColumnLabel(i);
                for (Field field : list) {
//                    Transient annTran = field.getAnnotation(Transient.class);
//                    if (annTran != null) { //忽略不持久化的字段
//                        continue;
//                    }
                    String annoColumnName =ReflectUtil.getAnnoColumnName(field);
                    // sql里面的字段名称，和model注解配置的字段名称一样才给赋值。否则不赋值
                    if (annoColumnName.equalsIgnoreCase(columnName)) {
                        Class paramType = ReflectUtil.getAnnoColumnType(field);
                        String methodName = "set" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
                        Method method = ReflectUtil.getMethod(clazz,methodName,paramType,field);

                        Object value= getRsValue(rs, paramType, annoColumnName,field);
                        ReflectUtil.setFieldValue(t, method, field, value);
                        continue;
                    }
                }
            }
        } catch (Exception e) {
            throw new UnCheckedException(e);
        }
        return t;
    }

    private Object getRsValue(ResultSet rs, Class type, String columnName, Field field) throws SQLException {
        Column annotation = field.getAnnotation(Column.class);
        if (annotation!=null&&annotation.type()!=null&&annotation.type()== ColumnType.Time) {
            return rs.getTimestamp(columnName);  //todo refactor  so ugly。
        }
        Object obj = null;
        if (type == String.class) {
            obj = rs.getString(columnName);
        } else if (type == Boolean.class || type == boolean.class) {
            obj = rs.getBoolean(columnName);
        } else if (type == Integer.class) {
            obj = rs.getInt(columnName);
        } else if (type == Long.class) {
            obj = rs.getLong(columnName);
        } else if (type == Double.class) {
            obj = rs.getDouble(columnName);
        } else if (type == Date.class) {
            obj = rs.getDate(columnName);
        }
        return obj;
    }




}
